package lwf.factory;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.SortedMap;
import java.util.StringTokenizer;
import java.util.TreeMap;

import net.lwf.exception.ExceptionUtil;

import lwf.handler.entities.MultipleChoice;
import lwf.handler.entities.Tenses;
import lwf.handler.entities.Vocabulary;


public class PropertyReader {
	
	private static PropertyReader instance = null;
	
	private ResourceBundle dataBundle = null;
	private ResourceBundle rWFBundle = null;
	private ResourceBundle wordImageBundle = null;
	private ResourceBundle sightWordsBundle = null;
	private ResourceBundle wordSentencesBundle = null;
	private ResourceBundle tensesBundle = null;
	private ResourceBundle antonymsBundle = null;
	private ResourceBundle homonymsBundle = null;
	private ResourceBundle sitemapBundle = null;
	private ResourceBundle wordsoundsBundle = null;
	private ResourceBundle shapeBundle = null;
	private ResourceBundle vocabQsBundle = null;
	private ResourceBundle vocabWordsBundle = null;
	
	//Will be populated from dataBundle resource (data.properties)
	private Map mapDays = null;
	private Map mapAnimals = null;
	private Map mapLiquids = null;
	private Map mapItems = null;
	private Map mapNames = null;
	private Map mapColors = null;
	private Map mapFruits = null;

	private SortedMap mapRwords = null; 
	private Map mapWordImages = null;
	private Map mapSightWords = null;
	private Map mapWordSentences = null;
	private List lstRWords = null;
	private List lstTenses = null;
	private Map mapAntonyms = null;
	private Map mapHomonyms = null;
	private Map mapSiteMap = null;
	private Map mapWordSounds = null;
	private Map mapShapeInfo = null;
	private List vocabQuestions = null;
	private List vocabWords = null;

	private PropertyReader() {
		init();
	}

	
	public synchronized final static PropertyReader getInstance(){
		if (instance == null) {
			instance = new PropertyReader();
		}
		return instance;
	}

	/**
	 * @return Returns the mapAnimals.
	 */
	public Map getAnimals() {
		return mapAnimals;
	}
	/**
	 * @return Returns the mapColors.
	 */
	public Map getColors() {
		return mapColors;
	}
	/**
	 * @return Returns the mapDays.
	 */
	public Map getDays() {
		return mapDays;
	}
	/**
	 * @return Returns the mapFruits.
	 */
	public Map getFruits() {
		return mapFruits;
	}
	/**
	 * @return Returns the mapItems.
	 */
	public Map getItems() {
		return mapItems;
	}
	/**
	 * @return Returns the mapLiquids.
	 */
	public Map getLiquids() {
		return mapLiquids;
	}
	/**
	 * @return Returns the mapNames.
	 */
	public Map getNames() {
		return mapNames;
	}
	
	public Map getRhymingWords() {
		if(mapRwords == null) {
			this.processRWF(rWFBundle);
		}
		return mapRwords;
	}
	
	public List getAllRhymingWords() {
		if(lstRWords == null) {
			this.processRWF(rWFBundle);
		}
		return lstRWords;
	}
	
	public Map getWordImages() {
		if(mapWordImages == null) {
			this.processWI(wordImageBundle);
		}
		return mapWordImages;
	}

//	public Map getSightWords() {
//		if(mapSightWords == null) {
//			this.processSW(sightWordsBundle);
//		}
//		return mapSightWords;
//	}
	
	public Map getWordSentences() {
		if(mapWordSentences == null) {
			this.processWS(wordSentencesBundle);
		}
		return mapWordSentences;
	}
	
	public List getTenses() {
		if(lstTenses == null) {
			this.processTenses(tensesBundle);
		}
		return lstTenses;
	}
	
	public Map getAntonyms() {
		if(mapAntonyms == null) {
			processAntonyms(antonymsBundle);
		}
		return mapAntonyms;
	}
	
	public Map getHomonyms() {
		if(mapHomonyms == null) {
			processHomonyms(homonymsBundle);
		}
		return mapHomonyms;
	}
	
	public Map getSiteMap() {
		if(mapSiteMap == null) {
			processSM(sitemapBundle);
		}
		return mapSiteMap;
	}
	
	public Map getWordSounds() {
		if(mapWordSounds == null) {
			processWordSounds(wordsoundsBundle);
		}
		return mapWordSounds;
	}
	
	public Map getShapeInfo() {
		if(mapShapeInfo == null) {
			processShapeInfo(shapeBundle);
		}
		return mapShapeInfo;
	}
	
	public List getVocabQuestions() {
		if(vocabQuestions == null) {
			processVocabQuestions(vocabQsBundle);
		}
		return vocabQuestions;
	}
	
	public List getVocabWords() {
		if(vocabWords == null) {
			processVocabWords(vocabWordsBundle);
		}
		return vocabWords;
	}
	
	//-----------------------------------------------------------------------------------
	// Private methods
	//-----------------------------------------------------------------------------------
	
	private void init() {
		try {
			if (dataBundle == null) {
				dataBundle = ResourceBundle.getBundle("general.data");
				this.toDetailedMap(dataBundle);
			}
		
			if(rWFBundle == null) {
				rWFBundle = ResourceBundle.getBundle("general.rhymingwordfamily");
				//this.processRWF(rWFBundle);
			}
			if(wordImageBundle == null) {
				wordImageBundle = ResourceBundle.getBundle("general.wordimages");
				//this.processWI(wordImageBundle);
			}
			if(sightWordsBundle == null) {
				sightWordsBundle = ResourceBundle.getBundle("general.sightwords");
				//this.processSW(sightWordsBundle);
			}
			if(wordSentencesBundle == null) {
				wordSentencesBundle = ResourceBundle.getBundle("general.wordsentenses");
				//this.processWS(wordSentencesBundle);
			}
			if(tensesBundle == null) {
				tensesBundle = ResourceBundle.getBundle("general.tenses");
			}
			if(antonymsBundle == null) {
				antonymsBundle = ResourceBundle.getBundle("general.antonyms");
			}
			if(homonymsBundle == null) {
				homonymsBundle = ResourceBundle.getBundle("general.homonyms");
			}
			if(wordsoundsBundle == null) {
				wordsoundsBundle = ResourceBundle.getBundle("general.wordsounds");
			}
			if(shapeBundle == null) {
				shapeBundle = ResourceBundle.getBundle("general.shapes");
			}
			if(vocabQsBundle == null) {
				vocabQsBundle = ResourceBundle.getBundle("general.vocabquestions");
			}
			if(vocabWordsBundle == null) {
				vocabWordsBundle = ResourceBundle.getBundle("general.vocabulary");
			}
		}
		catch(MissingResourceException mrex) {
			//throw new AppException(mrex);
			ExceptionUtil.logAndThrowException(PropertyReader.class, mrex);
		}
	}
	
	
	
	/**
	 * @return Returns the mapWp.
	 */
//	public Map getMapWp() {
//		return mapWp;
//	}
	
	private Map toMap(ResourceBundle resource) {
		Map mapdata = new HashMap();
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString();
			mapdata.put(key, resource.getString(key));
		}
			
		return mapdata;
	}
	
	private void processAntonyms(ResourceBundle resource) {
		if(mapAntonyms == null) {
			mapAntonyms = new HashMap();
		}
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString(); //1|1
			StringTokenizer stk = new StringTokenizer(key, "|");
			String levelKey = stk.nextToken();
			String data = resource.getString(key);
			Map mapdata = null;
			if(mapAntonyms.containsKey(levelKey)) {
				mapdata = (Map) mapAntonyms.get(levelKey);
			}
			else {
				mapdata = new HashMap();
			}
			StringTokenizer stk1 = new StringTokenizer(data, "=");
			String word = stk1.nextToken();
			String opposite = stk1.nextToken();
			mapdata.put(word, opposite);
			mapdata.put(opposite, word);
			//To big map
			mapAntonyms.put(levelKey, mapdata);
		}
	}
	
	private void processHomonyms(ResourceBundle resource) {
		
		if(mapHomonyms == null) {
			mapHomonyms = new HashMap();
		}
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString(); //1|1
			StringTokenizer stk = new StringTokenizer(key, "|");
			String levelKey = stk.nextToken();
			String data = resource.getString(key);
			List lstData = null;
			if(mapHomonyms.containsKey(levelKey)) {
				lstData = (List) mapHomonyms.get(levelKey);
			}
			else {
				lstData = new ArrayList();
			}
			lstData.add(data);
			//To big map
			mapHomonyms.put(levelKey, lstData);
		}
	}
	
	private void toDetailedMap(ResourceBundle resource) {
		mapDays = new HashMap();
		mapAnimals = new HashMap();
		mapLiquids = new HashMap();
		mapItems = new HashMap();
		mapNames = new HashMap();
		mapColors = new HashMap();
		mapFruits = new HashMap();
		
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString();
			StringTokenizer stk = new StringTokenizer(key, "|");
			String dataKey = stk.nextToken();
			String mapKey = stk.nextToken();
			if(dataKey.equals("1")) { //Days
				mapDays.put(mapKey, resource.getString(key));	
			}
			else if(dataKey.equals("2")) { //Animals
				mapAnimals.put(mapKey, resource.getString(key));
			}
			else if(dataKey.equals("3")) { //Liquids
				mapLiquids.put(mapKey, resource.getString(key));
			}
			else if(dataKey.equals("4")) { //Items
				mapItems.put(mapKey, resource.getString(key));
			}
			else if(dataKey.equals("5")) { //Names
				mapNames.put(mapKey, resource.getString(key));
			}
			else if(dataKey.equals("6")) { //Colors
				mapColors.put(mapKey, resource.getString(key));
			}
			else if(dataKey.equals("7")) { //Fruits
				mapFruits.put(mapKey, resource.getString(key));
			}			
		}
	}	
	
	private void processRWF(ResourceBundle resource) {
		lstRWords = new ArrayList();
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString();
			String value = resource.getString(key);
    		StringTokenizer stk = new StringTokenizer(value, "|");
    		List lstWords = new ArrayList();
    		//WordInfo winfo = new WordInfo();
    		while(stk.hasMoreTokens()) {
    			String word = stk.nextToken();
        		//lstWords.add(new WordInfo(word));
        		//lstRWords.add(new WordInfo(word));
        		lstWords.add(word);
        		lstRWords.add(word);
    		}
        	//Collections.sort(lstWords);
    		if(mapRwords == null) {
    			mapRwords = new TreeMap();
    		}
    		mapRwords.put(key, lstWords);
		}
	}
	
	private void processWI(ResourceBundle resource) {
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString();
			String value = resource.getString(key);
			List lstImages = new ArrayList();
			StringTokenizer stk = new StringTokenizer(value, "|");
    		while(stk.hasMoreTokens()) {
    			lstImages.add(stk.nextToken());
    		}    			
    		if(mapWordImages == null) {
    			mapWordImages = new HashMap();
    		}
    		mapWordImages.put(key, lstImages);
		}
	} 
	
	private void processSW(ResourceBundle resource) {
		mapSightWords = new HashMap();
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString();
			StringTokenizer stk = new StringTokenizer(key, "|");
			String levelKey = stk.nextToken();
			String word = resource.getString(key);
			List lstwords = null;
			if(mapSightWords.containsKey(levelKey)) {
				lstwords = (List) mapSightWords.get(levelKey);
			}
			else {
				lstwords = new ArrayList();
			}
			lstwords.add(word);
			Collections.sort(lstwords);
			mapSightWords.put(levelKey, lstwords);
		}
	}
	
	private void processWS(ResourceBundle resource) {
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString();
			String value = resource.getString(key);
    		StringTokenizer stk = new StringTokenizer(value, "|");

    		List lstSentences = new ArrayList();
        		while(stk.hasMoreTokens()) {
        			lstSentences.add(stk.nextToken());
        		}    			

    		if(mapWordSentences == null) {
    			mapWordSentences = new HashMap();
    		}
    		mapWordSentences.put(key, lstSentences);
		}
	}
	
	private void processTenses(ResourceBundle resource) {
		Enumeration enum1 = resource.getKeys();
		Tenses tense = null;
		while(enum1.hasMoreElements()) {
			
			String key = enum1.nextElement().toString();
			String value = resource.getString(key);
    		StringTokenizer stk = new StringTokenizer(value, "|");
    		if(lstTenses == null) {
    			lstTenses = new ArrayList();
    		}
    		tense = new Tenses(stk.nextToken(), stk.nextToken(), stk.nextToken());
    		lstTenses.add(tense);
		}
	}
	
	private void processSM(ResourceBundle resource) {
		if(mapSiteMap == null) {
			mapSiteMap = new HashMap();
		}
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString(); //1|1
			StringTokenizer stk = new StringTokenizer(key, "|");
			String levelKey = stk.nextToken();
			String data = resource.getString(key);
			Map mapdata = null;
			if(mapAntonyms.containsKey(levelKey)) {
				mapdata = (Map) mapAntonyms.get(levelKey);
			}
			else {
				mapdata = new HashMap();
			}
			StringTokenizer stk1 = new StringTokenizer(data, "=");
			String word = stk1.nextToken();
			String opposite = stk1.nextToken();
			mapdata.put(word, opposite);
			mapdata.put(opposite, word);
			//To big map
			mapAntonyms.put(levelKey, mapdata);
		}
	}
	
	private void processWordSounds(ResourceBundle resource) {
		if(mapWordSounds == null) {
			mapWordSounds = new HashMap();
		}
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString(); //br|1
			String data = resource.getString(key); //Comma separated words
			mapWordSounds.put(key, data);
		}
	}
	
	private void processShapeInfo(ResourceBundle resource) {
		if(mapShapeInfo == null) {
			mapShapeInfo = new HashMap();
		}
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString(); //Shape code
			String data = resource.getString(key); //Comma separated info
			mapShapeInfo.put(key, data);
		}
	}
	
	private void processVocabQuestions(ResourceBundle resource) {
		if(vocabQuestions == null) {
			vocabQuestions = new ArrayList();
		}
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			MultipleChoice mc = new MultipleChoice();
			String key = enum1.nextElement().toString(); //Shape code
			String data = resource.getString(key); 
			StringTokenizer stk = new StringTokenizer(data, "|");
			mc.setQuestion(stk.nextToken());
			mc.setAnswer(stk.nextToken());
			String choices = stk.nextToken();
			StringTokenizer stkchoices = new StringTokenizer(choices, ",");
			List lstchoices = new ArrayList(stkchoices.countTokens());
			while(stkchoices.hasMoreTokens()) {
				lstchoices.add(stkchoices.nextToken());
			}
			lstchoices.add(mc.getAnswer());
			mc.setAnswerChoices(lstchoices);
			vocabQuestions.add(mc);
		}
	}
	
	private void processVocabWords(ResourceBundle resource) {
		if(vocabWords == null) {
			vocabWords = new ArrayList();
		}
		Enumeration enum1 = resource.getKeys();
		while(enum1.hasMoreElements()) {
			String key = enum1.nextElement().toString(); //Shape code
			String data = resource.getString(key);
			Vocabulary vocab = new Vocabulary();
			vocab.setWord(key);
			vocab.setMeaning(data);
			vocabWords.add(vocab);
		}
	}
	
	public static void main (String[] args) {
		
	}
	
	
} //PropertyReader
